package com.example.shop.merchant.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.shop.common.api.ServiceReturn;
import com.example.shop.common.api.ServiceStateCode;
import com.example.shop.common.bo.maplocation.Location;
import com.example.shop.common.bo.maplocation.LocationInfo;
import com.example.shop.common.service.MapLocationService;
import com.example.shop.common.util.CachedThreadPoolUtil;
import com.example.shop.common.util.FileOptionUtil;
import com.example.shop.mapper.MerchantMapper;
import com.example.shop.merchant.dto.RegisterParam;
import com.example.shop.merchant.enums.MerchantState;
import com.example.shop.merchant.service.MerchantService;
import com.example.shop.pojo.Merchant;
import com.example.shop.rabbitmq.component.MerchantMessageComponent;
import com.example.shop.redis.enums.RedisKey;
import com.example.shop.redis.service.LettuceClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Service
public class MerchantServiceImpl implements MerchantService {

    @Autowired
    MerchantMapper merchantMapper;
    @Autowired
    MapLocationService mapService;
    @Autowired
    LettuceClient redisClient;
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Override
    public ServiceReturn<Boolean> checkRegisterParam(RegisterParam registerParam) {
        //商家号是否被注册过了
        QueryWrapper<Merchant> query = new QueryWrapper<>();
        query.eq("merchant_account",registerParam.getAccount());
        boolean exists = merchantMapper.exists(query);
        if(exists){
            return new ServiceReturn<>(ServiceStateCode.ACCOUNT_HAS_BEEN_REGISTER,false);
        }
        return new ServiceReturn<>(ServiceStateCode.SUCCESS,true);
    }

    @Transactional
    @Override
    public ServiceReturn<Boolean> register(RegisterParam registerParam) {
        Merchant merchant = registerParam.toMerchant();
        String resourceDir = merchant.getMerchantResourceDir();
        //使用默认头像名，方便更换头像
        String fileName = "avatar.png";
        merchant.setMerchantAvatar(resourceDir+fileName);

        //处理商家头像
        MultipartFile avatarFile = registerParam.getAvatarFile();
        if(avatarFile!=null){
            try {
                FileOptionUtil.asyncWrite(merchant.getMerchantAvatar(),avatarFile.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException("Merchant模块的MerchantServiceImpl的register文件写入头像出错");
            }
        }else{
            //否则使用默认头像
            FileOptionUtil.asyncCopyFile(merchant.getMerchantAvatar(),Merchant.RESOURCE_ROOT_DIR+"defaultAvatar.png");
        }

        //处理商家位置
        Location location = registerParam.getLocation();
        LocationInfo locationInfo = mapService.getLocationInfo(location);
        //设置该商家的定位位置
        merchant.setMerchantArea(locationInfo.getAddress());

        //声明创建一个该商家专属的消息队列，专门存放该商家的消息
        rabbitTemplate.execute(channel -> MerchantMessageComponent.queueDeclareAndBind(channel,merchant.getMerchantId()));

        //插入到数据库中
        merchantMapper.insert(merchant);

        //缓存该商家的所有信息，因为该商家接下来可能会去登录
        CacheMerchant(merchant,300);
        return new ServiceReturn<>(ServiceStateCode.SUCCESS,true);
    }

    @Override
    public ServiceReturn<Merchant> login(String account, String password) {
        Merchant merchant = redisClient.getValueAsKey(RedisKey.MERCHANT_ID + account, RedisKey.MERCHANT_INFO.getKey(), Merchant.class);
        if(merchant==null){
            QueryWrapper<Merchant> queryParam = new QueryWrapper<>();
            queryParam.eq("merchant_account",account);
            merchant = merchantMapper.selectOne(queryParam);
        }

        if(merchant!=null){
            if(merchant.getMerchantPassword().equals(password)){
                loginDeal(merchant);
                return new ServiceReturn<>(ServiceStateCode.SUCCESS,merchant);
            }
            return new ServiceReturn(ServiceStateCode.ACCOUNT_PASSWORD_NO_MATCH,null);
        }
        return new ServiceReturn(ServiceStateCode.NO_EXIST_MERCHANT,null);
    }

    @Override
    public void loginOut(Merchant merchant) {
        //设置用户为离线状态
        merchant.setMerchantState(MerchantState.offline.getState());
        CachedThreadPoolUtil.submit(()->{
            //更新用户表
            merchantMapper.updateFieldById(merchant.getMerchantId(),"merchant_state",MerchantState.offline.getState());
            //删除redis中保存的所有该商家信息
            redisClient.delKey(RedisKey.MERCHANT_INFO.getKey() + merchant.getMerchantId());
            redisClient.delKey(RedisKey.MERCHANT_ID + merchant.getMerchantAccount());
            if(merchant.getMerchantPhone()!=null){
                redisClient.delKey(RedisKey.MERCHANT_ID + merchant.getMerchantPhone());
            }
        });
    }


    public void loginDeal(Merchant merchant){
        merchant.setMerchantState(MerchantState.online.getState());
        CachedThreadPoolUtil.submit(()->{
            merchantMapper.updateFieldById(merchant.getMerchantId(),"merchant_state",MerchantState.online.getState());
        });
        CacheMerchant(merchant,-1);
    }

    public void CacheMerchant(Merchant merchant, int time){
        CachedThreadPoolUtil.submit(()->{
            long merchantId = merchant.getMerchantId();
            if(time == -1){
                redisClient.set(RedisKey.MERCHANT_INFO.getKey()+merchantId, merchant);
                redisClient.set(RedisKey.MERCHANT_ID +merchant.getMerchantAccount(),merchantId);
                if(merchant.getMerchantPhone()!=null){
                    redisClient.set(RedisKey.MERCHANT_ID +merchant.getMerchantPhone(),merchantId);
                }
            }else{
                redisClient.setEx(RedisKey.MERCHANT_INFO.getKey()+merchantId,merchant,time);
                redisClient.setEx(RedisKey.MERCHANT_ID +merchant.getMerchantAccount(),merchantId,time);
                if(merchant.getMerchantPhone()!=null){
                    redisClient.setEx(RedisKey.MERCHANT_ID +merchant.getMerchantPhone(),merchantId,time);
                }
            }
        });
    }
}
